﻿using AntdUI;
using FreeRedis;
using FreeSql.Internal;
using PosClient.Helper;
using PosClient.Interfaces;
using PosClient.Model;
using PosClient.Service;
using PosClient.View.PayForm;
using PosClient.View.PayForm.ViewModel;
using PosClient.View.SearchVipForm;
using ReactiveUI;
using Splat;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PosClient.View.MainForm.ViewModel
{
    public class MainViewModel: ReactiveObject
    {
        private IScheduler _mainScheduler;

        public ViewModelActivator Activator { get; }

        public enum SaleModeEnum
        {
            Sale = 1, // 销售
            AfterSale = 2 // 退货
        }

        #region 属性

        private BindingList<Plu> _PluList = new BindingList<Plu>();
        public BindingList<Plu> PluList
        {
            get => _PluList;
            set => this.RaiseAndSetIfChanged(ref _PluList, value);
        }

        private Plu _SelectPlu;
        public Plu SelectPlu
        {
            get => _SelectPlu;
            set => this.RaiseAndSetIfChanged(ref _SelectPlu, value);
        }

        private int _Index;
        public int Index
        {
            get => _Index;
            set => this.RaiseAndSetIfChanged(ref _Index, value);
        }

        private decimal _TotalCount;
        public decimal TotalCount
        {
            get => _TotalCount;
            set => this.RaiseAndSetIfChanged(ref _TotalCount, value);
        }

        private decimal _TotalAmount;
        public decimal TotalAmount
        {
            get => _TotalAmount;
            set => this.RaiseAndSetIfChanged(ref _TotalAmount, value);
        }

        private decimal _RemainPayAmount;
        public decimal RemainPayAmount
        {
            get => _RemainPayAmount;
            set => this.RaiseAndSetIfChanged(ref _RemainPayAmount, value);
        }

        private decimal _ExchangeAmount;
        public decimal ExchangeAmount
        {
            get => _ExchangeAmount;
            set => this.RaiseAndSetIfChanged(ref _ExchangeAmount, value);
        }

        private VipBase _VipBase = new VipBase();
        public VipBase VipBase
        {
            get => _VipBase;
            set => this.RaiseAndSetIfChanged(ref _VipBase, value);
        }

        private decimal _TotalDisAmount;
        public decimal TotalDisAmount
        {
            get => _TotalDisAmount;
            set => this.RaiseAndSetIfChanged(ref _TotalDisAmount, value);
        }

        private string _Barcode;
        public string Barcode
        {
            get => _Barcode;
            set => this.RaiseAndSetIfChanged(ref _Barcode, value);
        }

        private SaleModeEnum _SaleMode;
        public SaleModeEnum SaleMode
        {
            get => _SaleMode;
            set => this.RaiseAndSetIfChanged(ref _SaleMode, value);
        }
        #endregion

        #region Command

        /// <summary>
        /// 合计
        /// </summary>
        public ReactiveCommand<Unit, Unit> SummaryCommand { get; }

        /// <summary>
        /// 加1
        /// </summary>
        public ReactiveCommand<Unit, Unit> AddOneCommand { get; }

        /// <summary>
        /// 减1
        /// </summary>
        public ReactiveCommand<Unit, Unit> DelOneCommand { get; }

        /// <summary>
        /// 行情
        /// </summary>
        public ReactiveCommand<Unit, Unit> RemoveCommand { get; }

        /// <summary>
        /// 查询会员
        /// </summary>
        public ReactiveCommand<Unit, Unit> SearchVipCommand { get; }

        /// <summary>
        /// 获取Plu信息
        /// </summary>
        public ReactiveCommand<Unit, Result<Plu>> GetPluCommand { get; }

        /// <summary>
        /// 支付
        /// </summary>
        public ReactiveCommand<Unit, Unit> ConfirmPayCommand { get; }
        /// <summary>
        /// Vip打折
        /// </summary>
        public ReactiveCommand<Unit, Unit> VipDiscountCommand { get; set; }

        public ReactiveCommand<Unit, Unit> ClearCartCommand { get; set; }


        #endregion

        public MainViewModel(IScheduler mainScheduler)
        {
            _mainScheduler = mainScheduler;
            Activator = new ViewModelActivator();

            Locator.CurrentMutable.RegisterLazySingleton(() => new PayView());
            Locator.CurrentMutable.RegisterLazySingleton(() => new PayViewModel(mainScheduler));

            SummaryCommand = ReactiveCommand.Create(SummaryCommandImpl);
            AddOneCommand = ReactiveCommand.Create(AddOneCommandImpl);
            DelOneCommand = ReactiveCommand.Create(DelOneCommandImpl);
            RemoveCommand = ReactiveCommand.Create(RemoveCommandImpl);
            SearchVipCommand = ReactiveCommand.Create(SearchVipCommandImpl);
            GetPluCommand = ReactiveCommand.Create(GetPluCommandImpl);
            ConfirmPayCommand = ReactiveCommand.Create(ConfirmPayCommandImpl);
            VipDiscountCommand = ReactiveCommand.Create(VipDiscountCommandImpl);
            ClearCartCommand = ReactiveCommand.Create(ClearCartCommandImpl);

            this.WhenAnyValue(vm => vm.VipBase.VipCode).Subscribe(m =>
            {
                if (!string.IsNullOrEmpty(m))
                {
                    VipDiscountCommand.Execute().Subscribe();
                }
            });

        }

        private void SummaryCommandImpl()
        {
            TotalAmount = PluList.Sum(x => x.Amount);
            TotalCount = PluList.Sum(x => x.Count);
            TotalDisAmount = PluList.Sum(x => x.DisAmount);
        }

        private void AddOneCommandImpl()
        {
            if (SelectPlu != null)
            {
                SelectPlu.Count++;
                SelectPlu.Summary();
                Index = PluList.IndexOf(SelectPlu);
                SummaryCommandImpl();
            }
        }

        private void DelOneCommandImpl()
        {
            if (SelectPlu != null)
            {
                SelectPlu.Count--;
                SelectPlu.Summary();
                Index = PluList.IndexOf(SelectPlu);
                SummaryCommandImpl();
            }
        }

        private void RemoveCommandImpl()
        {
            if (PluList.Count == 0) return;
            Logger.AuditLogger.Audit($"删除商品 {PluList[Index]}");
            if (SelectPlu != null)
            {
                PluList.RemoveAt(Index);
            }
        }

        private void SearchVipCommandImpl()
        {
            Logger.AuditLogger.Audit($"进入查询会员窗口");
            SearchVipView searchVipView = new SearchVipView();
            searchVipView.ShowDialog();
            VipBase = searchVipView.ViewModel.Vip;
        }

        private Result<Plu> GetPluCommandImpl()
        {
            Result<Plu> result = new Result<Plu>()
            {
                Success = true,
                Message = "请求成功"
            };
            if (!string.IsNullOrEmpty(Barcode))
            {
                var pluService = Locator.Current.GetService<IPluService>();
                result = pluService.SearchPlu(Barcode);
                if (result.Success)
                {
                    AddorUpdateCartCommandImpl(result.Data);
                }
            }
            else
            {
                result.Success = false;
                result.Message = "请输入条码";
            }
            return result;
        }

        private void AddorUpdateCartCommandImpl(Plu plu)
        {
            var redis = FreeClient.Sqlite;
            Plu cartPlu = PluList.Where(g => g.PluCode == plu.PluCode
                && g.Tag != Plu.PluTag.Cut
                && g.Tag != Plu.PluTag.Change
                && g.Tag != Plu.PluTag.Present
                //&& g.CategoryCode.Substring(0,2) != "02"
                ).FirstOrDefault();
            if (cartPlu != null)
            {
                cartPlu.Count += plu.Count;
                cartPlu.Amount += plu.Amount;
                // cartGood.Price = Math.Round(cartGood.Amount / cartGood.Count, 2, MidpointRounding.AwayFromZero);
                cartPlu.OriginAmount += plu.OriginAmount;
                cartPlu.DisAmount += plu.DisAmount;
            }
            else
            {
                if (plu.CanDiscount == "1")
                {
                    int precision = 2;
                    decimal discount = ConvertVipDiscount(VipBase.VipLevel.LevelType);
                    decimal priceAfterDiscount = Math.Round(plu.OriginPrice * discount, precision, MidpointRounding.AwayFromZero);
                    plu.VipPrice = priceAfterDiscount;
                    plu.Tag = Plu.PluTag.Vip;
                    plu.Summary();
                }
                PluList.Add(plu);
            }
            SummaryCommandImpl();
        }


        private void ConfirmPayCommandImpl()
        {
            SummaryCommandImpl();
            PayView payView = new PayView();
            payView.ShowDialog();
        }

        private decimal ConvertVipDiscount(int vipType)
        {
            decimal DisCount = 0.00m;
            switch (vipType)
            {
                case 1:
                    DisCount = 98m;
                    break;
                case 2:
                    DisCount = 95m;
                    break;
                case 3:
                    DisCount = 93m;
                    break;
                case 4:
                    DisCount = 90m;
                    break;
                default:
                    DisCount = 100m;
                    break;
            }
            decimal discount = DisCount / 100m;
            return discount;
        }

        private void VipDiscountCommandImpl()
        {
            //>0为打折会员，暂定1打98折，2打95，3打93，4打90
            if (VipBase != null && VipBase.VipLevel.LevelType > 0)
            {
                foreach (Plu good in PluList.Where(x => x.Tag != Plu.PluTag.Promote 
                                                     && x.Tag != Plu.PluTag.Cut 
                                                     && x.Tag != Plu.PluTag.Present 
                                                     && x.Tag != Plu.PluTag.Change
                                                     && x.Tag != Plu.PluTag.ExChange
                                                     ))
                {
                    if (good.CanDiscount == "1")
                    {
                        int precision = 2;
                        decimal discount = ConvertVipDiscount(VipBase.VipLevel.LevelType);
                        decimal priceAfterDiscount = Math.Round(good.OriginPrice * discount, precision, MidpointRounding.AwayFromZero);
                        good.VipPrice = priceAfterDiscount;
                        good.Tag = Plu.PluTag.Vip;
                        good.Summary();
                        SummaryCommandImpl();
                    }
                }
            }
        }

        private void ClearCartCommandImpl()
        {
            if (VipBase != null)
            {
                VipBase = new VipBase
                {
                    VipCode = string.Format(" "),
                    PointCurrent = 0,
                    DepositCurrent = 0,
                    VipLevel = new VipLevel()
                    { 
                        LevelCode = "- -",
                        LevelName = "游客",
                        LevelType = -1
                    }
                };
            }
            SaleMode = SaleModeEnum.Sale;
            TotalAmount = 0;
            TotalCount = 0;
            if (PluList.Count > 0)
            {
                if ( MessageBox.Show("确认要清空购物车吗？", "提醒", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes)
                {
                    // 清空购物车
                    Index = -1;
                    TotalAmount = 0;
                    TotalCount = 0;
                    SaleMode = SaleModeEnum.Sale;
                    Barcode = string.Empty;
                    SelectPlu = null;
                    PluList.Clear();
                }
            }
        }
    }
}
